\section{tcp 如何保证可靠性}
 如同算法一样，解决问题，要学会先拆分成规模较小的子问题。

 这个问题可以分成3个子问题
 \begin{enumerate}
   \item tcp是什么
   \item 可靠性指什么
   \item 实现可靠性用了什么方法
 \end{enumerate}
参考的资料\href{https://www.youxuan8.net/article/36}{RFC793中文版--TCP},


\subsection{tcp是什么}
TCP的目的：通讯协议，用于保证在不可靠网络环境下能信息按序，可靠发送到通讯双方的主机中的进程

TCP的三大特征：面向连接的，可靠的，字节流  传输层通信协议

什么是连接： 一对一通讯才能连接，UDP那种一对多不属于面向连接

tcp连接的特征：RFC793中的描述，用于保证可靠性和流控的信息集合：socket、 序列号、 窗口大小

可靠性的目的：不管链路变化，tcp依然可以保证消息到达接收端。

字节流的特点：没有边界，可发送数据大小无限制，消息有序。

\subsection{什么是可靠性}
RFC793中有一个章节是 Reliable Communication, 定义的可靠性是能解决数据传输中会出现数据损坏，丢失，重复，乱序问题。

安全性设计区分：

一个是物理设备链接可靠出现的故障，一个是人为攻击。

tcp三次握手中前2次不能携带数据的设计规定，是为了防止tcp攻击导致接收方缓存耗尽。

\subsection{如何实现可靠性}
这个4个可靠性问题对应3种处理机制

\begin{description}
  \item[损坏:] tcp中增加校验码字段
  \item[丢失:] 超时重发，发送队列中每次发送会复制一份到重发队列，同时启动定时器，当定时器超时且未收到对方的ACK信息，此报文进行重发。
  \item[重复\&乱序:] 序列号 seq + ack，通过MSS设定TCP最大数据报文大小，超过大小被分段，每个段对应一个序号seq，
\end{description}



\section{tcp有哪些优化点}
\subsection{性能指标}
RTO
RTT

\subsection{kcp}
\subsection{quic}


\section{通信的限制}
\subsection{最小最大包长的限制原因}
以太网(IEEE 802.3)帧格式：

1、前导码（前同步码）：7字节0x55,一串1、0间隔，用于信号同步

2、帧开始定界符：1字节0xD5(10101011)，表示一帧开始

3、DA(目的MAC)：6字节

4、SA(源MAC)：6字节

5、类型/长度：2字节，0～1500保留为长度域值，1536～65535保留为类型域值(0x0600～0xFFFF)

6、数据：46～1500字节

7、帧校验序列(FCS)：4字节，使用CRC计算从目的MAC到数据域这部分内容而得到的校验和。

以CSMA/CD作为MAC算法的一类LAN称为以太网。CSMA/CD冲突避免的方法：先听后发、边听边发、随机延迟后重发。一旦发生冲突，必须让每台主机都能检测到。关于最小发送间隙和最小帧长的规定也是为了避免冲突。

考虑如下的情况，主机发送的帧很小，而两台冲突主机相距很远。在主机A发送的帧传输到B的前一刻，B开始发送帧。这样，当A的帧到达B时，B检测到冲突，于是发送冲突信号。假如在B的冲突信号传输到A之前，A的帧已经发送完毕，那么A将检测不到冲突而误认为已发送成功。由于信号传播是有时延的，因此检测冲突也需要一定的时间。这也是为什么必须有个最小帧长的限制。

按照标准，10Mbps以太网采用中继器时，连接的最大长度是2500米，最多经过4个中继器，因此规定对10Mbps以太网一帧的最小发送时间为51.2微秒。这段时间所能传输的数据为512位，因此也称该时间为512位时。这个时间定义为以太网时隙，或冲突时槽。512位＝64字节，这就是以太网帧最小64字节的原因。
512位时是主机捕获信道的时间。如果某主机发送一个帧的64字节仍无冲突，以后也就不会再发生冲突了，称此主机捕获了信道。

由于信道是所有主机共享的，如果数据帧太长就会出现有的主机长时间不能发送数据，而且有的发送数据可能超出接收端的缓冲区大小，造成缓冲溢出。为避免单一主机占用信道时间过长，规定了以太网帧的最大帧长为1500。

100Mbps以太网的时隙仍为512位时，以太网规定一帧的最小发送时间必须为5.12μs。

1000Mbps以太网的时隙增至512字节，即4096位时，4.096μs。

IP数据包长度问题总结
TCP/IP协议，涉及到四层：链路层、网络层、传输层、应用层。

其中以太网的数据帧在链路层

IP包在网络层

TCP或UDP包在传输层

TCP或UDP中的数据(Data)在应用层

它们的关系是数据帧{IP包{TCP或者UDP包{Data}}}

————————————————————————————————

在应用程序中我们用到的Data的长度最大是多少，直接取决于底层限制。

我们从下到上分析一下：

1.在链路层，由以太网的物理特性决定了数据帧的长度为（46+18）—（1500 + 18），其中的18是数据帧的头和尾，也就是说数据帧的内容最大为1500（不包括帧头和帧尾），即MTU(Maximum Transmission Unit)为1500；

2.在网络层，因为IP包的首部要占用20字节，所以这的MTU为1500-20 = 1480；

3.在传输层，对于UDP包的首部要占8字节，所以这的MTU为1480 - 8 = 1472；

所以，在应用层，您的Data最大长度为1472字节。（当我们UDP包中的数据多于1472时，发送方的IP层需要分片fragmentation进行传输，而在接收方IP层则需要进行数据报重组，由于UDP是不可靠的传输协议，如果分片丢失导致重组失败，将导致UDP数据包被丢弃。）

从上面的分析来看，普通的局域网环境下，UDP的数据最大是1472字节最好，避免分片重组。

但是在网络编程中，Internet中的路由器可能设置成不同的值（小于默认值），Internet上的标准MTU值为576，所以Internet的UDP编程时的数据长度最好在576 - 20 -8 = 548字节以内。

Mac OS点击系统偏好设置——网络——高级——硬件可以查看本机的MTU设置。

IP数据包的最大长度是64K字节（2\^16 -1），因为在IP包头中用2个字节描述报文长度，2个字节所能表示的最大数字就是2\^16-1 = 65536 -1 = 65535.

由于IP协议提供为上层协议分割和重组报文的功能，因此传输层协议的数据包长度原则上来说没有限制。实际上限制还是有的，因为IP包的标识字段终究不可能无限长，按照IPv4，上限是2\^32=4G字节。依照这种机制，TCP包头中就没有“包长度”字段，而完全依靠IP层去处理分帧。这就是为什么TCP常常被称作一种“流协议”的原因，开发者在使用TCP服务的时候，不必关心数据包的大小，只需要将SOCKET看作一条数据流的入口，往里面放数据就是了，TCP协议本身会进行拥塞/流量控制。

UDP则和TCP不同，UDP包头内有总长度字段，同样为2个字节，因此UDP数据包的总长度被限制为(2\^16-1)，这样恰好可以放进一个IP包内，使得UDP/IP协议栈的实现非常简单高效。65535再减去UDP头本身所占据的8个字节，UDP服务中的最大有效负载长度仅为65527.这个值也就是调用getsockopt()时指定SO\_MAC\_MSG\_SIZE所得到的返回值，任何使用SOCK\_DGRAM属性的socket,一次send的数据都不能超过这个值，否则必然得到一个错误。

那么，IP包提交给下层协议时将会得到怎样的处理呢？取决于数据链路层协议，一般得到数据链路层协议都会负责将IP包分割成更小的帧，然后在目的端重组它，在EtherNet上，数据链路帧的大小如开篇所述。而如果是IP over ATM,则IP包将被切分成一个一个的ATM Cell，大小为53字节。

\subsection{如何查看MTU设置}
MTU是Maximum Transmission Unit的缩写。意思是网络上传送的最大数据包。
Mac OS点击系统偏好设置——网络——高级——硬件可以查看本机的MTU设置。

Windows10 系统下该怎样设置 mtu 值呢？

步骤如下：
\begin{enumerate}
  \item 在开始菜单上单击右键，选择【命令提示符（管理员）】；
  \item 在命令提示符中输入：netsh interface ipv4 show subinterfaces 按下回车键查看当前的 mtu 值；
  \item 接着按下面格式输入：netsh interface ipv4 set subinterface "连接名" mtu=值 store=persistent
（如：netsh interface ipv4 set subinterface "WLAN" mtu=1492 store=persistent） 按下回车键，出现“确定”提示 则说明修改完成。
\end{enumerate}




查看方法和设置方法各有两种，分别是ifconfig和文件

ifconfig：

查看：ifconfig eth0

就可以找到MTU的信息

设置：ifconfig eth0 mtu 1500



文件：

查看：cat /sys/class/net/eth0/mtu

设置：echo "1460" > /sys/class/net/eth0/mtu


如何根据连接的网络或者 IP 来确定 mtu 的值呢？
1、同样先打开命令提示符（管理员）， 输入：ping -l 1472 -f www.baidu.com （探测百度为例），请求将一个不允许分割的 1472 字节的数据包发送出去；


2、若是出现传输失败，提示需要拆分数据包的情况，则说明当前网络的 MTU 值要比指定的 1472 小，因此我们就适当调小数据包的大小（比如 1450），输入：ping -l 1450 -f www.baidu.com 按下回车键；


3、如果出现传输成功，则说明当前网络的 MTU 值比 1450 要大。于是我们需要稍微调大数值（比如 1460），以便求得最为精确的网络 MTU 值，


4、通过取值之后我们再通过上述方法进行设置即可。


\section{通信实现策略}

\subsection{一台主机内两个程序如何用tcp/ip通信}
环回接口

大多数系统把IP地址127.0.0.1分配给这个接口，并命名为localhost。一个传给环回接口的IP数据报不能在任何网络上出现。
一旦传输层检测到目的端地址是环回地址时，应该可以省略部分传输层和所有网络层的逻辑操作。但是大多数的产品还是照样完成传输层和网络层的所有过程，只是当IP数据报离开网络层时把它返回给自己。

1) 传给环回地址（一般是127.0.0.1）的任何数据均作为IP输入。

2) 传给广播地址或多播地址的数据报复制一份传给环回接口，然后送到以太网上。这是因为广播传送和多播传送的定义包含主机本身。

3) 任何传给该主机IP地址的数据均送到环回接口。


\subsection{一台主机内内核态与用户态如何通信}

通过寄存器：函数调用的方式，包括系统调用和ioctl， ioctl是不想增加系统调用的情况下的一个特殊系统调用
通过内存：文件读写，映射物理内存
通过固定方式：信号

\begin{enumerate}
  \item 系统调用  + ioctl
  \item 文件读写
  \item 内存映射 mmap
  \item socket
  \item 信号传送
  \item 反向调用
\end{enumerate}
\subsubsection{系统调用}

\subsection{二台主机如何通信}
1、基于OSI/TCPIP构造通信报文
2、用网线相连

\subsection{三台主机如何通信}
2个网口
\subsection{几十台主机如何通信}
集线器
\subsection{几百台主机如何通信}
交换机
\subsection{几万台以上主机如何通信}
路由器
\subsection{运营商网络如何提高报文转发效率}
用MPLS表代替路由表

\section{通信安全问题}
\subsection{交换机中的设备如何实现设备间隔离}
VLAN
\subsection{路由器中的设备如何实现设备间隔离}

\begin{itemize}
     \item 子网掩码
     \item VPN
     \item
\end{itemize}

\section{二层链路层有几种格式头}

4种以太头
\begin{enumerate}
  \item Ehternet II
  \item Novell Ethernet
  \item IEEE 802.3/802.2
  \item IEEE 802.3 SNAP
\end{enumerate}

1980 DEC,Intel,Xerox制订了Ethernet I的标准；

1982 DEC,Intel,Xerox又制订了Ehternet II的标准；

1982 IEEE开始研究Ethernet的国际标准802.3；

1983 迫不及待的Novell基于IEEE的802.3的原始版开发了专用的Ethernet帧格式；

1985 IEEE推出IEEE 802.3规范；

后来为解决EthernetII与802.3帧格式的兼容问题推出折衷的Ethernet SNAP格式 。

(其中早期的Ethernet I已经完全被其他帧格式取代了所以现在Ethernet只能见到后面几种Ethernet的帧格式现在大部分的网络设备都支持这几种Ethernet的帧格式如:cisco的路由器在设定Ethernet接口时可以指定不同的以太网的帧格式:arpa,sap,snap,novell-ether)

 Ethernet II
是DIX以太网联盟推出的，它由6个字节的目的MAC地址，6个字节的源MAC地址，2个字节的类型域（用于表示装在这个Frame、里面数据的类型)，以上为Frame Header,接下来是46--1500 字节的数据，和4字节的帧校验）
\begin{figure}[htbp]
  \centering
  \includegraphics[width=10cm]{EthernetII}
  \caption{EthernetII}\label{EthernetII}
\end{figure}

Novell Ethernet
   它的帧头与Ethernet有所不同其中EthernetII帧头中的类型域变成了长度域， 后面接着的两个字节为0xFFFF用于标示这个帧是Novell Ether类型的Frame，由于前面的0xFFFF站掉了两个字节所以数据域缩小为44-1498个字节,帧校验不变。
\begin{figure}[htbp]
  \centering
  \includegraphics[width=10cm]{Novell_Ethernet}
  \caption{Novell Ethernet}\label{Novell_Ethernet}
\end{figure}

IEEE 802.3/802.2
   802.3的Frame Header和Ethernet II的帧头有所不同，它把EthernetII类型域变成了长度域(与Novell Ethernet相同)。其中又引入802.2协议(LLC)在802.3帧头后面添加了一个LLC首部,由DSAP(Destination Service Access Point) 1 byte,SSAP(Source SAP) 1 byte,一个控制域 1 byte! SAP用于表示帧的上层协议。
\begin{figure}[htbp]
  \centering
  \includegraphics[width=10cm]{IEEE802.3}
  \caption{IEEE 802.3/802.2}\label{IEEE802.3}
\end{figure}
Ethernet SNAP
Ethernet SNAP Frame与802.3/802.2 Frame的最大区别是增加了一个5 Bytes的SNAP ID，其中前面3个byte通常与源mac地址的前三个bytes相同，为厂商代码！有时也可设为0。后2 bytes 与Ethernet II的类型域相同。
\begin{figure}[htbp]
  \centering
  \includegraphics[width=10cm]{Ethernet_SNAP}
  \caption{Ethernet SNAP}\label{Ethernet_SNAP}
\end{figure}
Ethernet II和IEEE802.3是局域网里最常见的帧:

Ethernet II可以装载的数据长度是46---1500;

IEEE802.3 SAP可以装装的数据长度是43---1497;

IEEE 802.3 SNAP可以装载的数据长度是38---1492.

Ethernet II不提供MAC层的数据填充功能;

IEEE802.3 SAP和SNAP都提供数据填充功能.

因些,我们可以得出这样的结论:

Ethernet II比IEEE802.3 SAP和SNAP更适合于传输大量的数据,但Ethernet II缺乏对数据链路层的控制,不利于传输需要严格传输控制的数据.

实际中,我们会发现,大多数应用程序的以太网数据包都是Ethernet II帧的(如HTTP/Telnet/FTP/SMTP/POP3等应用),而交换机之间的BPDU是采用IEEE802.3 SAP帧,VLAN Trunk协议802.1Q和Cisco CDP都是采用IEEE802.3 SNAP帧.


\section{linux 内核进程cpu调度设计}
在工作中编写linux相关代码时，当前编写的代码什么时候会运行到，中断和不同进程的代码是怎么分配CPU运行的。内核态和用户态的代码有什么注意的地方，cpu占用率如何控制，时间的延时和定时处理如何实现，不同的时间函数API有什么区别，用错了会有什么后果。以下从总体系统设计的角度出发，结合工作中的相关问题进行个人角度分析。
